#include<iostream>
using namespace std;
#include<unistd.h>
#include<pthread.h>
#include<string>
#include<vector>
#include<assert.h>

#define NUM 10

class ThreadData
{
    public:
        pthread_t tid;
        char buffername[64];
};

class Thread_return {
    public:
        int exit_code;
        int eixt_text;
};

//这里就是一个可重入函数：
void* start_routine(void* arges){
   // string name = (const char*)arges;
    ThreadData* td = static_cast<ThreadData*>(arges);
    int cnt = 10;
    while(cnt){

        // cout<<"我是新线程,名称："<<name<<cnt--<<endl;
        // sleep(1);

        //证明是可重入函数
        // cout<<"cnt:"<<cnt<<":&cnt->"<<&cnt<<endl;
        // cnt--;
        // sleep(1);




        cout<<"我是新线程：名称："<<td->buffername<<": cnt :"<<cnt--<<endl;
        sleep(1);

        //线程终止接口:这里相当于创建一个线程就退出一个
       // pthread_exit(nullptr);


        //在新线程中制作一个野指针的问题，看看会有什么反应
        // int* p = nullptr;
        // *p = 0;//指针默认不能返回0号位置
        //事实上发生了端错误，并且整个进程一起退出了，因为发生错误会收到os发生的信号，信号是由进程接收的，默认的处理的行为就是终止进程。

    }
    //delete td;
    Thread_return* ret = new Thread_return();
    ret->exit_code = 1;
    ret->eixt_text = 666;
    // pthread_exit(nullptr);
    return (void*)ret;//(void*)ret = (void*)10
    

}

//1:验证线程健壮性的问题
int main(){
    //2：创建多线程
    vector<ThreadData*> threads;
    for(int i =0;i<NUM;i++){
        //创建不同名称的多线程
        //sleep(1);
        // pthread_t tid;
        // char buffer[64];
        // snprintf(buffer,sizeof buffer,"%s : %d","thread",i);
        // pthread_create(&tid,nullptr,start_routine,buffer);
        // sleep(1);
        //上面这样写会有问题，因为线程谁先运行是不清楚的，所以有可能主线程跑完了，还没有去执行新线程，这样就会出现不理想的情况

        sleep(1);
        //解决方法：使用一个类来封装
        ThreadData* td = new ThreadData();//构造函数，是在堆上面开辟空间
        snprintf(td->buffername,sizeof(td->buffername),"%s : %d","thread",i);
        pthread_create(&td->tid,nullptr,start_routine,td);
        threads.push_back(td);

        //test
        // pthread_t tid;
        // char* buffer = new char[64];
        // snprintf(buffer,sizeof buffer,"%s:%d","thread",i);
        // pthread_create(&tid,nullptr,start_routine,buffer);
        

    }


    //创建线程show
    for(auto& e: threads){
        cout<<"创建的线程："<<e->buffername<<":tid:"<<e->tid<<endl;
    }

    sleep(5);
    //在这里取消5个线程
    //取消的线程的返回值是-1
    for(int i = 0;i <threads.size()/2;i++){
        int cancel = pthread_cancel(threads[i]->tid);
        cout<<"线程取消成功:"<<threads[i]->buffername<<endl;

    }


    //线程的等待问题
    for(auto& e :threads){
        //要接受线程的退出信息，必须要一个载体
        //void* status = nullptr;
        Thread_return* status = nullptr; //这里返回的是一个结构体信息
        int ret = pthread_join(e->tid,(void**)&status);//第二个参数是输出型参数,这里是二级指针
        assert(ret == 0);

        //这里有一个问题，就是buffername打印出来是乱码，是因为我们已经退出了进程，空间都被释放了
       // cout<<"join "<<e->buffername<<"success "<<"status"<<(long long)status<<endl;
        cout<<"join "<<e->buffername<<"success "<<"status: "<<status->exit_code<<":"<<status->eixt_text<<endl;

        delete e;
    }

    while (true)
    {
        cout<<"我是主进程："<<endl;
        sleep(1);
    }
    
  








    // pthread_t tid;
    // pthread_create(&tid,nullptr,start_routine,(void*)"thread one");

    // while(true){
    //     cout<<"我是主线程："<<endl;
    //     sleep(1);
    // }


    return 0;
}